unit PtSettingsControlsCommon;

interface

uses
  Classes, Controls, Forms, TypInfo, Generics.Collections;

type
  TSystemToTitle = function (Str: string): string of object;

  ISettingsTypeEditor = interface
    ['{CC34F8FE-A2E6-4568-9B79-88682A3FB3E9}']
    function  GetValue: Variant;
    procedure SetValue(Value: Variant);
  end;

  TSettingsTypeEditorCreator = class
  protected
    fTypeKind: TTypeKind;
    function  CreateFrame(Owner, Parent: TWinControl): TWinControl; virtual; abstract;
  public
    constructor Create(ATypeKind: TTypeKind);
    property  TypeKind: TTypeKind read fTypeKind;
  end;

  TSettingsTypeEditorFactory = class
  private
    fCreators: TObjectList<TSettingsTypeEditorCreator>;
  protected
    procedure AddCreator(FrameCreator: TSettingsTypeEditorCreator);
  public
    constructor Create;
    destructor  Destroy; override;
    function  CreateFrame(Owner, Parent: TWinControl; const TypeKind: TTypeKind): TWinControl;
  end;

var
  EditorFactory: TSettingsTypeEditorFactory;

implementation

uses
  StdCtrls, Vcl.Samples.Spin;

type
  TSimpleCreator = class(TSettingsTypeEditorCreator)
  private
    fClass: TWinControlClass;
  protected
    function CreateFrame(Owner, Parent: TWinControl): TWinControl; override;
  public
    constructor Create(ATypeKind: TTypeKind; AClass: TWinControlClass);
  end;

  //  Editors

  TIntegerEdit = class(TSpinEdit, ISettingsTypeEditor)
  public
    function GetValue: Variant;
    procedure SetValue(Value: Variant);
  end;

  TTextEdit = class(TEdit, ISettingsTypeEditor)
  public
    function GetValue: Variant;
    procedure SetValue(Value: Variant);
  end;

  TEnumEdit = class(TComboBox, ISettingsTypeEditor)
  public
    function GetValue: Variant;
    procedure SetValue(Value: Variant);
  end;

  TEnumEditCreator = class(TSettingsTypeEditorCreator)
  protected
    function CreateFrame(Owner: TWinControl; Parent: TWinControl): TWinControl; override;
  end;

{ TSettingsTypeEditorCreator }

constructor TSettingsTypeEditorCreator.Create(ATypeKind: TTypeKind);
begin
  inherited Create;
  fTypeKind := ATypeKind;
end;

{ TSettingsTypeEditorFactory }

procedure TSettingsTypeEditorFactory.AddCreator(FrameCreator: TSettingsTypeEditorCreator);
begin
  fCreators.Add( FrameCreator )
end;

constructor TSettingsTypeEditorFactory.Create;

  procedure AddSimpleCreator(TypeKind: TTypeKind; ControlClass: TWinControlClass);
  begin
    AddCreator(TSimpleCreator.Create(TypeKind, ControlClass));
  end;

begin
  inherited;
  fCreators := TObjectList<TSettingsTypeEditorCreator>.Create;
  //  tkInteger
  AddSimpleCreator(tkInteger, TIntegerEdit);
  AddSimpleCreator(tkString,  TTextEdit);
  AddSimpleCreator(tkLString, TTextEdit);
  AddSimpleCreator(tkWString, TTextEdit);
  AddSimpleCreator(tkUString, TTextEdit);
  AddCreator(TEnumEditCreator.Create(tkEnumeration));
{
      , tkChar, tkWChar:
        SetOrdProp( Settings, Name, Value );

      tkSet:
        SetSetProp( Settings, Name, Value );

      tkFloat:
        SetFloatProp( Settings, Name, Value );

      tkInt64:
		    SetInt64Prop( Settings, Name, Value );
}
end;

function TSettingsTypeEditorFactory.CreateFrame(Owner, Parent: TWinControl; const TypeKind: TTypeKind): TWinControl;
var
  i : integer;
  Creator : TSettingsTypeEditorCreator;
begin
  Result  := nil;
  for i := 0 to fCreators.Count-1 do
    begin
      Creator := fCreators[i];
      if  Creator.TypeKind = TypeKind then
        begin
          Result  := Creator.CreateFrame(Owner, Parent);
          break;
        end;
    end;
end;

destructor TSettingsTypeEditorFactory.Destroy;
begin
  fCreators.Free;
  inherited;
end;

{ TSimpleCreator }

constructor TSimpleCreator.Create(ATypeKind: TTypeKind; AClass: TWinControlClass);
begin
  inherited Create(ATypeKind);
  fClass    := AClass;
end;

function TSimpleCreator.CreateFrame(Owner, Parent: TWinControl): TWinControl;
begin
  Result  := fClass.Create(Owner);
  Result.Parent := Parent;
end;

{ TIntegerEdit }

function TIntegerEdit.GetValue: Variant;
begin
  Result  := Self.Value
end;

procedure TIntegerEdit.SetValue(Value: Variant);
begin
  Self.Value  := Value
end;

{ TTextEdit }

function TTextEdit.GetValue: Variant;
begin
  Result  := Self.Text
end;

procedure TTextEdit.SetValue(Value: Variant);
begin
  Self.Text := Value
end;

{ TEnumEdit }

function TEnumEdit.GetValue: Variant;
begin
  Result  := Text
end;

procedure TEnumEdit.SetValue(Value: Variant);
begin
  ItemIndex := Items.IndexOf(Value)
end;

{ TEnumEditCreator }

function TEnumEditCreator.CreateFrame(Owner, Parent: TWinControl): TWinControl;
var
  EnumEdit: TEnumEdit;
begin
  EnumEdit  := TEnumEdit.Create(Owner);
  EnumEdit.Parent := Parent;
  EnumEdit.Style  := csDropDownList;

  Result    := EnumEdit;
end;

initialization
  EditorFactory := TSettingsTypeEditorFactory.Create;

finalization
  EditorFactory.Free;

end.
